import { message } from 'antd';

/**
 * 错误类型枚举
 */
export enum ErrorType {
  NETWORK = 'network',           // 网络错误
  BUSINESS = 'business',         // 业务错误
  UNAUTHORIZED = 'unauthorized', // 未授权
  FORBIDDEN = 'forbidden',       // 禁止访问
  NOT_FOUND = 'not_found',      // 资源不存在
  SERVER_ERROR = 'server_error', // 服务器错误
  TIMEOUT = 'timeout',          // 超时
  UNKNOWN = 'unknown'           // 未知错误
}

/**
 * 错误信息接口
 */
interface ErrorInfo {
  type: ErrorType;
  message: string;
  code?: number;
  url?: string;
  timestamp: number;
  count: number;
}

/**
 * 错误管理器配置
 */
interface ErrorManagerConfig {
  /** 错误去重时间窗口（毫秒），默认3秒 */
  deduplicationWindow: number;
  /** 批量显示延迟（毫秒），默认100ms */
  batchDelay: number;
  /** 最大错误缓存数量，默认50 */
  maxCacheSize: number;
  /** 是否启用错误合并，默认true */
  enableBatching: boolean;
  /** 是否在控制台输出调试信息，默认false */
  debug: boolean;
}

/**
 * 全局错误管理器
 * 
 * 功能特性：
 * 1. 错误去重：相同错误在时间窗口内只显示一次
 * 2. 批量合并：短时间内的多个错误可以合并显示
 * 3. 智能分类：按错误类型和状态码进行分组
 * 4. 延迟显示：避免瞬间大量错误提示
 * 5. 内存管理：自动清理过期错误缓存
 */
class ErrorManager {
  private config: ErrorManagerConfig;
  private errorCache = new Map<string, ErrorInfo>();
  private batchTimer: NodeJS.Timeout | null = null;
  private pendingErrors: ErrorInfo[] = [];

  constructor(config: Partial<ErrorManagerConfig> = {}) {
    this.config = {
      deduplicationWindow: 3000,
      batchDelay: 100,
      maxCacheSize: 50,
      enableBatching: false,
      debug: false,
      ...config
    };

    // 定期清理过期缓存
    setInterval(() => this.cleanExpiredCache(), 10000);
  }

  /**
   * 处理错误
   * @param type 错误类型
   * @param message 错误消息
   * @param code HTTP状态码
   * @param url 请求URL
   */
  handleError(type: ErrorType, message: string, code?: number, url?: string): void {
    const errorKey = this.generateErrorKey(type, message, code);
    const now = Date.now();

    // 检查是否为重复错误
    const existingError = this.errorCache.get(errorKey);
    if (existingError && (now - existingError.timestamp) < this.config.deduplicationWindow) {
      // 更新错误计数和时间戳
      existingError.count++;
      existingError.timestamp = now;
      
      if (this.config.debug) {
        console.log(`[ErrorManager] 重复错误已去重: ${message} (计数: ${existingError.count})`);
      }
      return;
    }

    // 创建新的错误信息
    const errorInfo: ErrorInfo = {
      type,
      message,
      code,
      url,
      timestamp: now,
      count: 1
    };

    // 更新缓存
    this.errorCache.set(errorKey, errorInfo);
    this.cleanCacheIfNeeded();

    if (this.config.debug) {
      console.log(`[ErrorManager] 新错误: ${message}`, errorInfo);
    }

    // 处理错误显示
    if (this.config.enableBatching) {
      this.addToBatch(errorInfo);
    } else {
      this.showError(errorInfo);
    }
  }

  /**
   * 生成错误唯一键
   */
  private generateErrorKey(type: ErrorType, message: string, code?: number): string {
    return `${type}:${code || 'no-code'}:${message}`;
  }

  /**
   * 添加到批量处理队列
   */
  private addToBatch(errorInfo: ErrorInfo): void {
    this.pendingErrors.push(errorInfo);

    // 清除之前的定时器
    if (this.batchTimer) {
      clearTimeout(this.batchTimer);
    }

    // 设置新的批量处理定时器
    this.batchTimer = setTimeout(() => {
      this.processBatch();
    }, this.config.batchDelay);
  }

  /**
   * 处理批量错误
   */
  private processBatch(): void {
    if (this.pendingErrors.length === 0) return;

    const errors = [...this.pendingErrors];
    this.pendingErrors = [];
    this.batchTimer = null;

    if (this.config.debug) {
      console.log(`[ErrorManager] 处理批量错误: ${errors.length} 个`);
    }

    // 按类型分组
    const groupedErrors = this.groupErrorsByType(errors);

    // 显示分组后的错误
    for (const [type, errorList] of groupedErrors.entries()) {
      if (errorList.length === 1) {
        this.showError(errorList[0]);
      } else {
        this.showBatchedErrors(type, errorList);
      }
    }
  }

  /**
   * 按错误类型分组
   */
  private groupErrorsByType(errors: ErrorInfo[]): Map<ErrorType, ErrorInfo[]> {
    const groups = new Map<ErrorType, ErrorInfo[]>();
    
    for (const error of errors) {
      const existing = groups.get(error.type) || [];
      existing.push(error);
      groups.set(error.type, existing);
    }

    return groups;
  }

  /**
   * 显示单个错误
   */
  private showError(errorInfo: ErrorInfo): void {
    const { type, message: errorMessage, count } = errorInfo;
    const displayMessage = count > 1 ? `${errorMessage} (${count}次)` : errorMessage;

    switch (type) {
      case ErrorType.UNAUTHORIZED:
        message.error(displayMessage);
        break;
      case ErrorType.FORBIDDEN:
        message.warning(displayMessage);
        break;
      case ErrorType.NETWORK:
        message.error(displayMessage);
        break;
      case ErrorType.SERVER_ERROR:
        message.error(displayMessage);
        break;
      case ErrorType.BUSINESS:
        message.error(displayMessage);
        break;
      default:
        message.error(displayMessage);
    }
  }

  /**
   * 显示批量错误
   */
  private showBatchedErrors(type: ErrorType, errors: ErrorInfo[]): void {
    const totalCount = errors.reduce((sum, error) => sum + error.count, 0);
    const uniqueMessages = [...new Set(errors.map(e => e.message))];

    let batchMessage: string;
    if (uniqueMessages.length === 1) {
      batchMessage = `${uniqueMessages[0]} (${totalCount}次)`;
    } else {
      batchMessage = `发生了 ${totalCount} 个${this.getTypeDisplayName(type)}错误`;
    }

    this.showError({
      type,
      message: batchMessage,
      timestamp: Date.now(),
      count: 1
    });
  }

  /**
   * 获取错误类型显示名称
   */
  private getTypeDisplayName(type: ErrorType): string {
    const typeNames = {
      [ErrorType.NETWORK]: '网络',
      [ErrorType.BUSINESS]: '业务',
      [ErrorType.UNAUTHORIZED]: '认证',
      [ErrorType.FORBIDDEN]: '权限',
      [ErrorType.NOT_FOUND]: '资源',
      [ErrorType.SERVER_ERROR]: '服务器',
      [ErrorType.TIMEOUT]: '超时',
      [ErrorType.UNKNOWN]: '未知'
    };
    return typeNames[type] || '未知';
  }

  /**
   * 清理过期缓存
   */
  private cleanExpiredCache(): void {
    const now = Date.now();
    const expiredKeys: string[] = [];

    for (const [key, errorInfo] of this.errorCache.entries()) {
      if (now - errorInfo.timestamp > this.config.deduplicationWindow * 2) {
        expiredKeys.push(key);
      }
    }

    expiredKeys.forEach(key => this.errorCache.delete(key));

    if (this.config.debug && expiredKeys.length > 0) {
      console.log(`[ErrorManager] 清理过期缓存: ${expiredKeys.length} 个`);
    }
  }

  /**
   * 清理缓存（如果超过最大数量）
   */
  private cleanCacheIfNeeded(): void {
    if (this.errorCache.size <= this.config.maxCacheSize) return;

    // 按时间戳排序，删除最旧的条目
    const entries = Array.from(this.errorCache.entries())
      .sort(([, a], [, b]) => a.timestamp - b.timestamp);

    const toDelete = entries.slice(0, entries.length - this.config.maxCacheSize);
    toDelete.forEach(([key]) => this.errorCache.delete(key));

    if (this.config.debug) {
      console.log(`[ErrorManager] 清理缓存: 删除 ${toDelete.length} 个旧条目`);
    }
  }

  /**
   * 获取错误统计信息
   */
  getStats(): { totalErrors: number; errorsByType: Record<string, number> } {
    const errorsByType: Record<string, number> = {};
    let totalErrors = 0;

    for (const errorInfo of this.errorCache.values()) {
      totalErrors += errorInfo.count;
      errorsByType[errorInfo.type] = (errorsByType[errorInfo.type] || 0) + errorInfo.count;
    }

    return { totalErrors, errorsByType };
  }

  /**
   * 清空所有缓存
   */
  clear(): void {
    this.errorCache.clear();
    this.pendingErrors = [];
    if (this.batchTimer) {
      clearTimeout(this.batchTimer);
      this.batchTimer = null;
    }
  }

  /**
   * 更新配置
   */
  updateConfig(newConfig: Partial<ErrorManagerConfig>): void {
    this.config = { ...this.config, ...newConfig };
  }
}

// 创建全局错误管理器实例
export const globalErrorManager = new ErrorManager({
  debug: import.meta.env.MODE === 'development'
});

/**
 * 便捷的错误处理函数
 */
export const handleApiError = {
  /**
   * 处理网络错误
   */
  network: (message: string = '网络连接失败') => {
    globalErrorManager.handleError(ErrorType.NETWORK, message);
  },

  /**
   * 处理业务错误
   */
  business: (message: string, code?: number) => {
    globalErrorManager.handleError(ErrorType.BUSINESS, message, code);
  },

  /**
   * 处理未授权错误
   */
  unauthorized: (message: string = '未授权，请重新登录') => {
    globalErrorManager.handleError(ErrorType.UNAUTHORIZED, message, 401);
  },

  /**
   * 处理禁止访问错误
   */
  forbidden: (message: string = '拒绝访问') => {
    globalErrorManager.handleError(ErrorType.FORBIDDEN, message, 403);
  },

  /**
   * 处理资源不存在错误
   */
  notFound: (message: string = '请求资源不存在') => {
    globalErrorManager.handleError(ErrorType.NOT_FOUND, message, 404);
  },

  /**
   * 处理服务器错误
   */
  serverError: (message: string = '服务器内部错误', code?: number) => {
    globalErrorManager.handleError(ErrorType.SERVER_ERROR, message, code || 500);
  },

  /**
   * 处理超时错误
   */
  timeout: (message: string = '请求超时') => {
    globalErrorManager.handleError(ErrorType.TIMEOUT, message);
  },

  /**
   * 处理HTTP状态码错误
   */
  httpStatus: (status: number, message?: string, url?: string) => {
    let errorType: ErrorType;
    let defaultMessage: string;

    switch (status) {
      case 401:
        errorType = ErrorType.UNAUTHORIZED;
        defaultMessage = '未授权，请重新登录';
        break;
      case 403:
        errorType = ErrorType.FORBIDDEN;
        defaultMessage = '拒绝访问';
        break;
      case 404:
        errorType = ErrorType.NOT_FOUND;
        defaultMessage = '请求资源不存在';
        break;
      case 500:
        errorType = ErrorType.SERVER_ERROR;
        defaultMessage = '服务器内部错误';
        break;
      default:
        errorType = ErrorType.UNKNOWN;
        defaultMessage = `请求失败 (${status})`;
    }

    globalErrorManager.handleError(
      errorType,
      message || defaultMessage,
      status,
      url
    );
  }
};

export default globalErrorManager;